//***************************************************************************//
//*
//* 内容摘要：跨平台TS文件录制实现
//*	
//* 当前版本：V1.0		
//* 作    者：zhfayuan
//* 完成日期：2015-12-26
//**************************************************************************//
#if !defined(TS_MUX_H)
#define TS_MUX_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SDTsMuxCrc.h"
#include "SDCommon.h"
#include "SDLog.h"
#include "SDMutex.h"
#include "CmdProtocolStruct.h"

#include "mpeg-ts.h"
#include "mpeg-ts-proto.h"


#define TS_PACKET_HEADER               4
#define TS_PACKET_SIZE                 188
#define TS_SYNC_BYTE                   0x47
#define TS_PAT_PID                     0x00
#define TS_PMT_PID                     0xFFF

#define TS_H264_PID                    0x100
#define TS_HEVC_PID                    0x101
#define TS_AAC_PID                     0x102

#define TS_H264_STREAM_ID              0xE0
#define TS_HEVC_STREAM_ID              0xE0
#define TS_AAC_STREAM_ID               0xC0
#define PMT_STREAM_TYPE_H264_VIDEO     0x1B
#define PMT_STREAM_TYPE_HEVC_VIDEO     0x24
#define PMT_STREAM_TYPE_AAC_AUDIO      0x0F
#define MAX_ONE_FRAME_SIZE             1024 * 1024
#define	ADTS_HEADER_LENGTH			   7

#ifdef WIN32
typedef signed __int64       int64_t;
typedef unsigned __int64     uint64_t;
#endif

class CTsMux
{
public:
	CTsMux();
	virtual ~CTsMux();

public:
	//录制文件名[不负责路径创建]、是否追加方式打开文件
	BOOL CreateTsMux(const char* pFileName,BYTE byVideoCodec,BYTE byAudioCodec,BOOL bAdd=TRUE);
	void CloseTsMux();
	//输入视频单个NALU或整帧码流，时间戳时基90KHZ
	BOOL PutVideoEsPacket(BYTE byCodec,char *pBuf, int nLen, unsigned long nTimestamp);
	//输入一帧音频ADTS包，时间戳时基90KHZ
	BOOL PutAudioEsPacket(BYTE byCodec,char *pBuf, int nLen, unsigned long nTimestamp);
    //获取本次写入的时长
	UINT GetCurrDuartion();
	//获得本次录制目前已写入的字节数MB[不加锁 不绝对精确]
	UINT GetCurrWriteSizeMB();

	UINT GetCurrWriteSizeByte();

private:
	BOOL PutH264VideoEsPacket(char *pBuf, int nLen, unsigned long nTimestamp);
	BOOL PutHEVCVideoEsPacket(char *pBuf, int nLen, unsigned long nTimestamp);


private:
	//TS录制模块所需的回调函数实现
	static void* TsAlloc(void* param, size_t bytes);
	static void TsFree(void* param, void* packet);
	static void TsWrite(void* param, const void* packet, size_t bytes);
	//判断当前帧是否为关键帧

public:
	//本次写入文件的字节数
	uint64_t m_unFileWriteSize;
	//录制的TS文件
	FILE *m_pVideo_Audio_Ts_File;
private:

	//TS录制模块
	void* m_pTsMuxer;
	//音视频轨ID
	int	m_nVideoTsTrackId;
	int	m_nAudioTsTrackId;

	//当前写入的TS包数目
	unsigned int m_nWritePacketNum;

	//写文件互斥锁
	void *m_pvFileWrite;
	//对外接口锁
	void *m_pvVideo;
	void *m_pvAudio;
	BOOL m_bTsMuxClose;
	
	unsigned long m_nVideoStartTimestamp;
	unsigned long m_nVideoPrevTimestamp;
    //文件开始的时间
	unsigned int m_unTimeOfFileBegin;
    //音视频编码方式
    BYTE    m_byAudioCodec;
    BYTE    m_byVideoCodec;
};

#endif
